/******************************************************************/
/*                                                                */
/*  Winpooch : Windows Watchdog                                   */
/*  Copyright (C) 2004-2005  Benoit Blanchon                      */
/*                                                                */
/*  This program is free software; you can redistribute it        */
/*  and/or modify it under the terms of the GNU General Public    */
/*  License as published by the Free Software Foundation; either  */
/*  version 2 of the License, or (at your option) any later       */
/*  version.                                                      */
/*                                                                */
/*  This program is distributed in the hope that it will be       */
/*  useful, but WITHOUT ANY WARRANTY; without even the implied    */
/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       */
/*  PURPOSE.  See the GNU General Public License for more         */
/*  details.                                                      */
/*                                                                */
/*  You should have received a copy of the GNU General Public     */
/*  License along with this program; if not, write to the Free    */
/*  Software Foundation, Inc.,                                    */
/*  675 Mass Ave, Cambridge, MA 02139, USA.                       */
/*                                                                */
/******************************************************************/


/******************************************************************/
/* Build configuration                                            */
/******************************************************************/

#define TRACE_LEVEL	2 /* warning */


/******************************************************************/
/* Includes                                                       */
/******************************************************************/

// module's interface
#include "HookFile.h"

// standard headers
#include <tchar.h>

// project's headers
#include "Assert.h"
#include "Hooks.h"
#include "SpyDllInt.h"
#include "strlcpy.h"
#include "Trace.h"


/******************************************************************/
/* Exported function : CreateFileW                                */
/******************************************************************/

HANDLE WINAPI Hook_CreateFileW (LPCWSTR	lpFileName,
				DWORD	dwDesiredAccess,
				DWORD	dwShareMode, 
				LPSECURITY_ATTRIBUTES lpSecurityAttributes,
				DWORD	dwCreationDistribution,
				DWORD	dwFlagsAndAttributes,
				HANDLE	hTemplateFile) 
{
  DWORD nReaction ;
  TCHAR szFilePath[MAX_PATH] ;
  
  TRACE_INFO (TEXT("%ls (0x%X)\n"), lpFileName, dwDesiredAccess) ;

  // get file path
  if( ! GetFullPathName (lpFileName, MAX_PATH, szFilePath, NULL) )
    _tcslcpy (szFilePath, lpFileName, MAX_PATH) ;

  // log call  
  if( dwDesiredAccess & GENERIC_WRITE )
    nReaction = SpyInt_CatchCall (REASON_FILE_WRITE, TEXT("s"), szFilePath) ;
  else
    nReaction = SpyInt_CatchCall (REASON_FILE_READ, TEXT("s"), szFilePath) ;

  if( nReaction != RULE_ACCEPT ) return INVALID_HANDLE_VALUE ;
  
  return Real_CreateFileW (lpFileName, dwDesiredAccess,	dwShareMode, 
			   lpSecurityAttributes, dwCreationDistribution,
			   dwFlagsAndAttributes, hTemplateFile)  ;
}

/******************************************************************/
/* Exported function : CreateFileW                                */
/******************************************************************/

HANDLE WINAPI Real_CreateFileW (LPCWSTR	lpFileName,
				DWORD	dwDesiredAccess,
				DWORD	dwShareMode, 
				LPSECURITY_ATTRIBUTES lpSecurityAttributes,
				DWORD	dwCreationDistribution,
				DWORD	dwFlagsAndAttributes,
				HANDLE	hTemplateFile) 
{
  PROC	pfnStub = Hooks_GetStubAddress (HOOKS_CREATEFILEW) ;
  
  TRACE_INFO (TEXT("%ls (0x%X)\n"), lpFileName, dwDesiredAccess) ;

  ASSERT (pfnStub!=NULL) ;

  return (HANDLE)pfnStub (lpFileName, dwDesiredAccess, dwShareMode, 
			  lpSecurityAttributes, dwCreationDistribution,
			  dwFlagsAndAttributes, hTemplateFile) ;
}


/******************************************************************/
/* Exported function : DeleteFileW (hooked)                       */
/******************************************************************/

BOOL WINAPI Hook_DeleteFileW (LPCWSTR lpFileName) 
{
  DWORD		nReaction ;
  TCHAR		tszFilePath[MAX_PATH] ;

  TRACE_INFO (TEXT("%ls\n"), lpFileName) ;

  if( ! _tcscmp(lpFileName,TEXT("DBWIN_DATA_READY")) )
    TRACE_WARNING ("PUTAIN !!!!!!!\n") ;

  //
  // get file path of existing file
  //
  if( ! GetFullPathName (lpFileName, MAX_PATH, tszFilePath, NULL) )
    _tcslcpy (tszFilePath, lpFileName, MAX_PATH) ;

  //
  // check if write is allowed 
  //
  nReaction = SpyInt_CatchCall (REASON_FILE_WRITE, TEXT("s"), tszFilePath) ;
  switch( nReaction )
    {
    case RULE_REJECT:
      SetLastError (ERROR_ACCESS_DENIED) ;
      return FALSE ;
    case RULE_FEIGN:
      SetLastError (ERROR_SUCCESS) ;
      return TRUE ;
    }

  // call real API function
  return Real_DeleteFileW (lpFileName) ;
}


/******************************************************************/
/* Exported function : DeleteFileW (not hooked)                   */
/******************************************************************/

BOOL WINAPI Real_DeleteFileW (LPCWSTR lpFileName) 
{
  PROC	pfnStub = Hooks_GetStubAddress (HOOKS_DELETEFILEW) ;
  
  TRACE_INFO (TEXT("%ls\n"), lpFileName) ;
  
  ASSERT (pfnStub!=NULL) ;
  
  return (BOOL) pfnStub (lpFileName) ;
}


/******************************************************************/
/* Exported function : MoveFileWithProgressW (hooked)             */
/******************************************************************/

BOOL	WINAPI	Hook_MoveFileWithProgressW (LPCWSTR lpExistingFileName,
					    LPCWSTR lpNewFileName,
					    LPPROGRESS_ROUTINE lpProgressRoutine,
					    LPVOID lpData,
					    DWORD dwFlags)
{
  DWORD		nReaction ;
  TCHAR		tszFilePath[MAX_PATH] ;

  TRACE_INFO (TEXT("%ls -> %ls\n"), lpExistingFileName, lpNewFileName) ;

  if( lpExistingFileName!=NULL )
    {
      //
      // get file path of existing file
      //
      if( ! GetFullPathName (lpExistingFileName, MAX_PATH, tszFilePath, NULL) )
	_tcslcpy (tszFilePath, lpExistingFileName, MAX_PATH) ;
      
      //
      // check if read or delete is allowed 
      //
      if( lpNewFileName!=NULL )
	nReaction = SpyInt_CatchCall (REASON_FILE_READ, TEXT("s"), tszFilePath) ;
      else
	nReaction = SpyInt_CatchCall (REASON_FILE_WRITE, TEXT("s"), tszFilePath) ;

      switch( nReaction )
	{
	case RULE_REJECT:
	  SetLastError (ERROR_ACCESS_DENIED) ;
	  return FALSE ;
	case RULE_FEIGN:
	  SetLastError (ERROR_SUCCESS) ;
	  return TRUE ;
	}
    }

  if( lpNewFileName!=NULL )
    {
      //
      // get file path of new file
      //
      if( ! GetFullPathName (lpNewFileName, MAX_PATH, tszFilePath, NULL) )
	_tcslcpy (tszFilePath, lpNewFileName, MAX_PATH) ;
      
      //
      // check if write is allowed 
      //
      nReaction = SpyInt_CatchCall (REASON_FILE_WRITE, TEXT("s"), tszFilePath) ;
      switch( nReaction )
	{
	case RULE_REJECT:
	  SetLastError (ERROR_ACCESS_DENIED) ;
	  return FALSE ;
	case RULE_FEIGN:
	  SetLastError (ERROR_SUCCESS) ;
	  return TRUE ;
	}
    }

  // call real API function
  return Real_MoveFileWithProgressW (lpExistingFileName, lpNewFileName,
				     lpProgressRoutine, lpData, dwFlags) ;
}


/******************************************************************/
/* Exported function : MoveFileWithProgressW (not hooked)         */
/******************************************************************/

BOOL WINAPI Real_MoveFileWithProgressW (LPCWSTR lpExistingFileName,
					LPCWSTR lpNewFileName,
					LPPROGRESS_ROUTINE lpProgressRoutine,
					LPVOID lpData,
					DWORD dwFlags)
{
  PROC	pfnStub = Hooks_GetStubAddress (HOOKS_MOVEFILEWITHPROGRESSW) ;
  
  TRACE_INFO (TEXT("%ls -> %ls\n"), lpExistingFileName, lpNewFileName) ;
  
  ASSERT (pfnStub!=NULL) ;
  
  return (BOOL) pfnStub (lpExistingFileName, lpNewFileName,
			 lpProgressRoutine, lpData, dwFlags) ;
}
